#pragma once

#include<functional>
#include <memory>

#include "noncopyable.h"
#include "Timestamp.h"

class EventLoop;


// Channel 理解为通道 封装sockfd和其感兴趣的event 如EPOLLIN EPOLLOUT等事件
// 还绑定了poller返回的具体事件
class Channel:noncopyable
{
public:
    using EventCallback = std::function<void()>;
    using ReadEventCallback = std::function<void(Timestamp)>;

    Channel(EventLoop* Loop,int fd);
    ~Channel();

    // fd得到poller通知以后 处理事件
    void handleEvent(Timestamp recvTime);
    // 设置回调函数对象                                       // cb为将亡值  
    void setReadCallback(ReadEventCallback cb){readCallback_=std::move(cb);}
    void setWriteCallback(EventCallback cb){writeCallback_=std::move(cb);}
    void setCloseCallback(EventCallback cb){closeCallback_=std::move(cb);}
    void setErrorCallback(EventCallback cb){errorCallback_=std::move(cb);}

    // 防止当channel被手动remove掉后 channel还在执行回调操作
    void tie(const std::shared_ptr<void>&);

    int fd() const {return fd_;}
    int index() {return index_;}
    int events() const {return events_;} // 返回当前需要监听的事件类型
    
    void set_index(int idx) {index_=idx;}
    void set_revents(int revt) {revents_=revt;} // 设置内核返回的就绪事件
    

    // 设置fd感兴趣的事件
    void enableReading() {events_|=kReadEvent;update();}
    void enableWriting() {events_|=kWriteEvent;update();}

    // 取消fd感兴趣的事件
    void disableReading() {events_&=~kReadEvent;update();}
    void disableWriting() {events_&=~kWriteEvent;update();}
    void disableAll() {events_=kNoneEvent;update();}

    // 判断当前fd事件状态
    bool isReading() const {return events_&kReadEvent;}
    bool isWriting() const {return events_&kWriteEvent;}
    bool isNoneEvent() const {return events_==kNoneEvent;} //判断当前是否没有监听任何事件

    
    // one loop per thread
    EventLoop* ownerLoop() {return loop_;}
    void remove();
private:

    void update();
    void handleEventWithGuard(Timestamp recvTime);
    
    static const int kNoneEvent;
    static const int kReadEvent;
    static const int kWriteEvent;

    EventLoop* loop_; // 事件循环
    const int fd_; // poller监听的对象
    int  events_; // 注册fd感兴趣的事件
    int revents_; // poller返回的具体发生的事件
    int index_; 

    std::weak_ptr<void> tie_;
    bool tied_; 


    // 因为channel通道里面能够获知fd最终发生的具 体事件revents 所以它负责具体事件的回调操作
    ReadEventCallback readCallback_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;

};
